extends CharacterBody2D

var debug_mode: bool = false  # 调试模式开关
var damage: float = 30.0
var target: Vector2
var explosion_radius: float = 100.0
var has_exploded: bool = false
var is_rolling: bool = true
var explosion_timer: float = 0.0
var is_ashcurse: bool = false  # 是否是诅咒哥布林的炸弹
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity") * 2.0  # 增加重力影响
var throw_direction = Vector2.ZERO
var throw_force = 400.0  # 投掷力度
var throw_height_factor = 1.0  # 降低投掷高度系数
var throw_arc_height = 200.0  # 抛物线最大高度
var roll_speed = 150.0   # 保持原有滚动速度
var bounce_factor = 0.4  # 降低弹跳系数
var player_bounce_factor = 0.4  # 与玩家碰撞的反弹系数
var friction = 0.95     # 增加地面摩擦力
var air_resistance = 0.999  # 空气阻力
var ground_rotation_factor = 0.8  # 地面旋转系数
var max_ground_speed = 200.0  # 降低最大速度限制
var initial_position = Vector2.ZERO  # 初始位置
var total_roll_distance = 0.0  # 总滚动距离
var max_roll_distance = 300.0  # 最大滚动距离，超过此距离将爆炸
var bomb_radius = 10.0  # 炸弹半径，用于计算旋转
var angular_velocity = 0.0  # 角速度
var angular_damping = 0.98  # 角速度衰减系数
var last_collision_point = Vector2.ZERO  # 上次碰撞点
var last_collision_normal = Vector2.ZERO  # 上次碰撞法线
var max_bounce_count = 3  # 最大弹跳次数
var current_bounce_count = 0  # 当前弹跳次数
var bounce_sound_cooldown = 0.0  # 弹跳声音冷却时间
var roll_sound_cooldown = 0.0  # 滚动声音冷却时间
var min_velocity_for_effects = 50.0  # 触发效果的最小速度
var has_shadow = true  # 是否有阴影
var impact_speed = 0.0  # 添加碰撞速度变量
var close_range: bool = false  # 是否是近距离投掷

# 添加未声明的变量
var frames_since_creation: int = 0  # 创建后经过的帧数
var ground_contact_count: int = 0  # 地面接触次数
var has_touched_ground = false  # 添加是否已经触地的标记
var ground_timer = 0.0  # 添加落地计时器

@onready var animated_sprite: AnimatedSprite2D = $AnimatedSprite2D
@onready var collision_shape: CollisionShape2D = $CollisionShape2D
@onready var explosion_area: Area2D = $ExplosionArea

# 粒子效果节点，可以在场景编辑器中添加
var bounce_particles = null
var roll_particles = null
var shadow = null

func _ready():
	# 设置碰撞层
	collision_layer = 8  # 炸弹层
	collision_mask = 3   # 与地面(2)和玩家(1)碰撞
	
	# 添加帧变化信号连接
	animated_sprite.frame_changed.connect(_on_frame_changed)
	
	# 设置物理材质
	var physics_material = PhysicsMaterial.new()
	physics_material.friction = 0.3  # 较低的摩擦力，让炸弹容易被推动
	physics_material.bounce = 0.6    # 与bounce_factor相匹配
	physics_material.absorbent = false  # 不吸收动量
	physics_material = physics_material
	
	# 设置为可以被推动
	collision_layer = collision_layer | 4  # 添加可推动物体层
	
	# 记录初始位置，用于计算滚动距离
	initial_position = global_position
	
	# 强制播放未爆炸动画
	if is_ashcurse:
		animated_sprite.play("bomb1_ashcurse")
	else:
		animated_sprite.play("bomb1")
	
	# 确保精灵的旋转中心点在中心
	animated_sprite.centered = true
	
	# 计算投掷轨迹
	if target:
		# 计算到目标的距离和方向
		var throw_direction_raw = (target - global_position).normalized()
		# 根据是否近距离投掷调整目标位置
		var distance_offset = 50.0 if close_range else 100.0
		var adjusted_target = target + throw_direction_raw * distance_offset
		var distance = adjusted_target.distance_to(global_position)
		throw_direction = (adjusted_target - global_position).normalized()
		
		# 根据距离调整投掷角度和力度
		var angle = PI / 3 if close_range else PI / 4  # 近距离60度，远距离45度
		
		# 根据距离计算初始速度
		var v0 = sqrt((distance * gravity) / sin(2 * angle))  # 计算初始速度
		v0 = min(v0, throw_force)  # 限制最大速度
		
		# 设置初始速度
		velocity.x = v0 * cos(angle) * throw_direction.x
		velocity.y = -v0 * sin(angle)  # 向上的速度
		
		if debug_mode:
			print("炸弹设置 - 近距离模式:", close_range)
			print("原始目标位置: ", target)
			print("调整后的目标位置: ", adjusted_target, "，偏移量:", distance_offset)
			print("计算的初速度:", v0, "，角度:", rad_to_deg(angle), "度")
	else:
		# 如果没有目标，默认向右投掷
		throw_direction = Vector2(1, 0)
		velocity = Vector2(throw_force, -throw_force * throw_height_factor)
	
	# 确保投掷方向不为零
	if throw_direction.x == 0:
		throw_direction.x = sign(velocity.x)
	
	# 设置动画朝向
	animated_sprite.flip_h = (throw_direction.x < 0)
	
	# 设置初始角速度
	angular_velocity = 0.0  # 初始不旋转
	
	# 播放投掷声音
	play_throw_sound()
	
	if debug_mode:
		print("炸弹已创建，目标位置: ", target, "，初始速度: ", velocity, "，固定投掷方向: ", throw_direction)
		print("精灵位置: ", animated_sprite.position, "，是否居中: ", animated_sprite.centered, "，偏移: ", animated_sprite.offset)

# 创建简单的阴影效果
func create_shadow():
	shadow = Sprite2D.new()
	shadow.texture = animated_sprite.sprite_frames.get_frame_texture(animated_sprite.animation, 0)
	shadow.modulate = Color(0, 0, 0, 0.3)  # 半透明黑色
	shadow.scale = Vector2(0.7, 0.3)  # 扁平化
	shadow.z_index = -1  # 确保在炸弹下方
	add_child(shadow)
	
func _physics_process(delta):
	frames_since_creation += 1
	
	# 应用重力
	velocity.y += gravity * delta
	
	# 在空中时应用空气阻力
	if not is_on_floor():
		velocity *= air_resistance
		has_touched_ground = false  # 重置触地标记
		ground_timer = 0.0  # 重置计时器
	else:
		# 检查是否第一次触地
		if not has_touched_ground:
			has_touched_ground = true
			ground_timer = 1.0  # 设置1秒计时器
			adjust_position_to_ground()  # 确保贴地
		
		# 在地面上时，根据速度自然计算角速度
		angular_velocity = velocity.x / bomb_radius
		# 应用地面摩擦力
		velocity.x *= friction
		
		# 添加轻微的向下力以保持贴地
		velocity.y += 5.0
	
	# 更新落地计时器
	if has_touched_ground and ground_timer > 0 and not has_exploded:
		ground_timer -= delta
		if ground_timer <= 0:
			_explode()
	
	# 检测与玩家的碰撞并处理推动
	for i in get_slide_collision_count():
		var collision = get_slide_collision(i)
		var collider = collision.get_collider()
		
		# 如果碰撞的是玩家且未爆炸
		if collider and collider.is_in_group("player") and not has_exploded:
			# 获取玩家的速度
			var player_velocity = collider.velocity if collider.has_method("get_velocity") else Vector2.ZERO
			
			# 计算反弹方向
			var normal = collision.get_normal()
			
			# 如果是从上方碰到玩家
			if normal.y < -0.5:  # 检查是否主要是垂直碰撞
				velocity.y = -abs(velocity.y) * player_bounce_factor * 0.5  # 进一步降低垂直反弹
				velocity.x += player_velocity.x * 0.3  # 减少获得的水平速度
			else:  # 侧面碰撞
				# 反弹效果
				velocity = velocity.bounce(normal) * player_bounce_factor
				# 添加一些玩家的速度，但减少影响
				velocity.x += sign(player_velocity.x) * min(abs(player_velocity.x), 150) * 0.5
			
			# 防止卡住，但减小分离力
			if abs(global_position.x - collider.global_position.x) < 20:
				velocity.x += sign(global_position.x - collider.global_position.x) * 60
	
	# 应用移动
	move_and_slide()
	
	if has_exploded:
		# 爆炸后继续应用物理效果，包括旋转
		animated_sprite.rotation += angular_velocity * delta
		
		# 如果在地面上，应用摩擦力减缓滚动
		if is_on_floor():
			velocity.x *= friction * 0.95  # 爆炸后增加额外摩擦力
			
			# 如果速度很小，完全停止
			if abs(velocity.x) < 5:
				velocity.x = 0
		return
	
	# 倒计时声音冷却
	if bounce_sound_cooldown > 0:
		bounce_sound_cooldown -= delta
	if roll_sound_cooldown > 0:
		roll_sound_cooldown -= delta
	
	# 更新阴影位置
	update_shadow()
	
	# 如果在地面上
	if is_on_floor():
		# 物理弹跳效果
		impact_speed = abs(velocity.y)
		velocity.y = -impact_speed * bounce_factor
		
		# 计算滚动距离
		total_roll_distance += abs(velocity.x) * delta
		
		# 如果滚动距离超过最大值，准备爆炸
		if total_roll_distance > max_roll_distance:
			explosion_timer = 0.5  # 0.5秒后爆炸
			if debug_mode:
				print("炸弹滚动距离达到上限，准备爆炸，总滚动距离: ", total_roll_distance)
		
		# 播放弹跳粒子效果和声音
		if impact_speed > min_velocity_for_effects:
			emit_bounce_particles(impact_speed, get_floor_normal())
			play_bounce_sound(impact_speed)
	
	if explosion_timer > 0:
		explosion_timer -= delta
		if explosion_timer <= 0:
			_explode()
	
	# 应用角速度到精灵旋转
	animated_sprite.rotation += angular_velocity * delta
	
	# 确保旋转角度在合理范围内
	while animated_sprite.rotation > PI * 2:
		animated_sprite.rotation -= PI * 2
	while animated_sprite.rotation < -PI * 2:
		animated_sprite.rotation += PI * 2
	
	if debug_mode and frames_since_creation % 10 == 0:
		print("炸弹当前速度: ", velocity, "，位置: ", global_position, "，动画旋转: ", animated_sprite.rotation, "，角速度: ", angular_velocity)

# 更新阴影位置
func update_shadow():
	if shadow:
		# 只在地面上显示阴影
		if is_on_floor():
			shadow.visible = true
			shadow.scale = Vector2(0.7, 0.3)
			shadow.modulate = Color(0, 0, 0, 0.3)
			shadow.global_position = global_position + Vector2(0, 15)
		else:
			# 在空中时隐藏阴影
			shadow.visible = false

# 调整炸弹位置，确保紧贴地面
func adjust_position_to_ground():
	if not is_on_floor():
		return
	
	# 使用射线检测获取地面位置
	var space_state = get_world_2d().direct_space_state
	var query = PhysicsRayQueryParameters2D.create(global_position, global_position + Vector2.DOWN * 20)
	query.collision_mask = collision_mask  # 使用相同的碰撞掩码
	query.exclude = [self]  # 排除自身
	var result = space_state.intersect_ray(query)
	
	if result:
		# 获取圆形碰撞体的半径
		var circle_shape = collision_shape.shape as CircleShape2D
		if circle_shape:
			# 平滑地调整到地面位置，考虑圆形碰撞体的半径
			var target_y = result.position.y - circle_shape.radius
			global_position.y = lerp(global_position.y, target_y, 0.5)
			
			# 如果速度很小且在地面上，确保完全停止
			if abs(velocity.y) < 10 and is_on_floor():
				velocity.y = 0

# 发射弹跳粒子效果
func emit_bounce_particles(impact_speed, normal):
	if bounce_particles:
		# 根据碰撞法线设置粒子发射方向
		var emission_direction = -normal
		bounce_particles.process_material.direction = Vector3(emission_direction.x, emission_direction.y, 0)
		
		# 根据冲击速度调整粒子数量和速度
		var intensity = clamp(impact_speed / 500, 0.3, 1.0)
		bounce_particles.amount = int(10 * intensity)
		bounce_particles.process_material.initial_velocity_min = 20 * intensity
		bounce_particles.process_material.initial_velocity_max = 50 * intensity
		
		# 触发粒子发射
		bounce_particles.restart()
		bounce_particles.emitting = true

# 发射滚动粒子效果
func emit_roll_particles():
	if roll_particles and is_on_floor():
		# 设置粒子发射方向与滚动方向相反
		var emission_direction = Vector2(-sign(velocity.x), -0.5).normalized()
		roll_particles.process_material.direction = Vector3(emission_direction.x, emission_direction.y, 0)
		
		# 根据滚动速度调整粒子数量和频率
		var intensity = clamp(abs(velocity.x) / max_ground_speed, 0.2, 1.0)
		roll_particles.amount = int(5 * intensity)
		roll_particles.process_material.emission_box_extents.x = 5 * intensity
		
		# 确保粒子正在发射
		if not roll_particles.emitting:
			roll_particles.emitting = true

# 播放投掷声音
func play_throw_sound():
	# 这里可以连接到AudioStreamPlayer来播放声音
	pass

# 播放弹跳声音
func play_bounce_sound(impact_speed):
	if bounce_sound_cooldown <= 0:
		# 根据冲击速度调整音量
		var volume_db = linear_to_db(clamp(impact_speed / 500, 0.3, 1.0))
		
		# 这里可以连接到AudioStreamPlayer来播放声音
		# 例如: $BounceSound.volume_db = volume_db; $BounceSound.play()
		
		# 设置声音冷却时间，避免声音重叠
		bounce_sound_cooldown = 0.2
		
		if debug_mode:
			print("播放弹跳声音，音量: ", volume_db)

# 播放滚动声音
func play_roll_sound(_delta):
	if roll_sound_cooldown <= 0 and is_on_floor():
		# 根据滚动速度调整音量和音高
		var speed_factor = clamp(abs(velocity.x) / max_ground_speed, 0.2, 1.0)
		var volume_db = linear_to_db(speed_factor)
		var pitch_scale = lerp(0.8, 1.2, speed_factor)
		
		# 这里可以连接到AudioStreamPlayer来播放声音
		# 例如: $RollSound.volume_db = volume_db; $RollSound.pitch_scale = pitch_scale; $RollSound.play()
		
		# 设置声音冷却时间，声音应该循环播放
		roll_sound_cooldown = 0.3 / speed_factor  # 速度越快，声音循环越快
		
		if debug_mode and frames_since_creation % 30 == 0:
			print("播放滚动声音，音量: ", volume_db, "，音高: ", pitch_scale)

func _explode():
	if has_exploded:
		return
		
	has_exploded = true
	
	# 只改变视觉效果，不改变物理状态
	if is_ashcurse:
		animated_sprite.play("bomb2_ashcurse")
	else:
		animated_sprite.play("bomb2")
	
	# 停止粒子效果
	if bounce_particles:
		bounce_particles.emitting = false
	if roll_particles:
		roll_particles.emitting = false
		
	# 隐藏阴影
	if shadow:
		shadow.visible = false

func apply_explosion_damage():
	# 对范围内的目标造成伤害
	var bodies = explosion_area.get_overlapping_bodies()
	for body in bodies:
		if body.has_method("take_damage"):
			var distance = global_position.distance_to(body.global_position)
			var damage_multiplier = 1.0 - (distance / explosion_radius)
			if damage_multiplier > 0:
				body.take_damage(damage * damage_multiplier, global_position)
				if debug_mode:
					print("炸弹对 ", body.name, " 造成伤害: ", damage * damage_multiplier)
				
				if is_ashcurse and body.has_method("apply_curse"):
					body.apply_curse(damage * 0.5, 3.0)
					if debug_mode:
						print("诅咒炸弹对 ", body.name, " 施加诅咒")

func _on_frame_changed():
	# 检查是否是爆炸动画且到达第9帧
	if has_exploded and (animated_sprite.animation == "bomb2" or animated_sprite.animation == "bomb2_ashcurse"):
		if animated_sprite.frame == 8:  # 因为帧索引从0开始，所以第9帧是索引8
			apply_explosion_damage()
			if debug_mode:
				print("第9帧触发爆炸伤害")

func _on_animated_sprite_animation_finished():
	if animated_sprite.animation.begins_with("bomb2"):  # 爆炸动画播放完毕
		if debug_mode:
			print("炸弹爆炸动画结束，销毁炸弹")
		queue_free()

func _on_body_entered(_body):
	# 移除此函数中的爆炸触发逻辑，避免提前爆炸
	pass
